import { ipcMain, Notification } from 'electron';
import fs from 'node:fs';
import path from 'node:path';

/**
 * 好友消息文件对象
 */
type Message_File = {
  friendId: string;
  friendName: string;
  hisMessage: Array<{
    time: number;
    message: string;
  }>;
  myMessage: Array<{
    time: number;
    message: string;
  }>;
};


type Own_Message = {
  userId: string;
  friendId: string;
  friendName: string;
  time: number;
  message: string;
};

// 自己发送消息的缓存 Map<time, {time, message}>
const OwnMessageCache: Map<number, Own_Message> = new Map();

/**
 * 好友消息文件映射 Map<friendId, {friendId, friendName, hisMessage, myMessage}>
 */
const friendsMessageMap: Map<string, Message_File> = new Map();

/**
 * 好友消息文件集合 Set<friendId>
 */
const friendsMessageSet: Set<string> = new Set();

ipcMain.on('show-system-message', (_event, title, body) => {
  const notification = {
    title: title,
    body: body
  };
  new Notification(notification).show();
});

// 初始化好友消息文件
ipcMain.on(
  'init-chat-message-files',
  async (
    event,
    userId: string,
    friends: Array<{ friendId: string; friendName: string }>
  ) => {
    event.sender.send(
      'init-chat-message-files',
      await initMessageFile(userId, friends)
    );
  }
);

// 缓存自己发送的消息
ipcMain.on('cache-own-message', async (event, data: Own_Message) => {
  OwnMessageCache.set(data.time, data);
  console.log('cache-own-message数据:', data);
  //创建用户消息文件，如果不存在则创建，存在则无效
  await createMessageFile(data.userId, data.friendId, data.friendName);
  event.sender.send('cache-own-message', true);
});

// 通过缓存保存消息到消息文件
ipcMain.on('save-own-message', async (event, time) => {
  const message = OwnMessageCache.get(time);
  console.log('从缓存中获取到的消息：', message);
  if (message) {
    event.sender.send('save-own-message', await saveOwnMessage(message));
  } else {
    event.sender.send('save-own-message', false);
  }
});

/**
 * 保存自己发送的消息
 */
const saveOwnMessage = async (data: Own_Message): Promise<boolean> => {
  const friendMessage = friendsMessageMap.get(data.friendId);
  if (friendMessage) {
    console.log('保存时的好友消息：',friendMessage);
    console.log('保存时的本地消息：',data);
    friendMessage.myMessage.push({ time: data.time, message: data.message });
    console.log('保存后的好友消息：',friendMessage);
    try {
      console.log('写入的文件：',friendMessage);
      fs.writeFileSync(
        path.resolve(`${data.userId}\\${data.friendId}.json`),
        JSON.stringify(friendMessage, null, 2)
      );
      return true;
    } catch (error) {
      console.log('保存文件错误：',error);
      return false;
    }
  } else {
    return true;
  }
};

// 保存对方私聊消息
ipcMain.on(
  'save-target-message',
  async (
    event,
    senderId: string,
    receiverId: string,
    timestamp: number,
    message: string,
    senderName: string
  ) => {
    console.log('save-target-message数据：',senderId,receiverId,timestamp,message,senderName);
    event.sender.send(
      'save-target-message',
      //保存
      await saveTargetMessage(
        senderId,
        receiverId,
        timestamp,
        message,
        senderName
      )
    );
  }
);

// 获取指定好友的私聊消息
ipcMain.on('get-chat-message', (event, friendId) => {
  event.sender.send(
    'get-chat-message',
    friendsMessageMap.get(friendId)
  );
});

// 初始化好友消息文件
const initMessageFile = async (
  userId: string,
  friends: Array<{ friendId: string; friendName: string }>
): Promise<any> => {
  const promises: Promise<any>[] = [];
  for (const item of friends) {
    promises.push(readMessageFile(userId, item.friendId, item.friendName));
  }
  const result = await Promise.all(promises);
  // 把获取到到私聊列表保存到内存中
  result.forEach((item) => {
    // 保存消息记录
    friendsMessageMap.set(item.friendId, item);
    //避免私聊列表重复
    friendsMessageSet.add(item.friendId);
  });
  console.log('初始化消息文件完成');
  return result;
};

const readMessageFile = (
  userId: string,
  friendId: string,
  friendName: string
) => {
  return new Promise<Message_File>((resolve, reject) => {
    fs.readFile(
      path.resolve(`${userId}\\${friendId}.json`),
      'utf-8',
      (err, data) => {
        if (err) {
          if (err.code === 'ENOENT') {
            let tempJson = {
              friendId: friendId,
              friendName: friendName,
              hisMessage: [],
              myMessage: []
            };
            fs.writeFileSync(
              path.resolve(`${userId}\\${friendId}.json`),
              JSON.stringify(tempJson, null, 2),
              'utf-8'
            );
            resolve(tempJson);
            console.log('文件不存在，当前的缓存数据：',tempJson);
          }
          reject(void 0);
        } else {
          resolve(JSON.parse(data.toString()));
        }
      }
    );
  });
};

/**
 * 尝试创建用户消息文件
 * @param senderId 发送方ID
 * @param receiverId 接收方ID
 * @param senderName 发送方名字
 * @returns
 */
const createMessageFile = async (
  senderId: string,
  receiverId: string,
  receiverName: string
): Promise<Message_File | undefined> => {
  //创建空的好友消息缓存
  let friendsMessage: Message_File = {
    friendId: senderId,
    friendName: receiverName,
    hisMessage: [],
    myMessage: []
  };
  const temp = friendsMessageMap.get(senderId);
  console.log('createMessageFile函数数据：',senderId,receiverId,receiverName);
  // 查找set里有没有对应的好友的消息，有就覆盖缓存，没有就创建文件
  if (!friendsMessageSet.has(senderId)) {
    if (temp) {
      friendsMessage = temp;
      return temp;
    } else {
      // 没有就创建对应的好友消息文件
      try {
        friendsMessage = await readMessageFile(
          senderId,
          receiverId,
          receiverName
        );
        return friendsMessage;
      } catch (error) {
        console.log('尝试创建用户消息文件出错：', error);
        return void 0;
      }
    }
  } else {
    if (temp) {
      friendsMessage = temp;
      return friendsMessage;
    } else {
      return void 0;
    }
  }
};

/**
 * 保存对方用户的消息
 * @param senderId 发送方id
 * @param receiverId 接收方id
 * @param timestamp 时间戳
 * @param message 消息明文
 */
const saveTargetMessage = async (
  senderId: string,
  receiverId: string,
  timestamp: number,
  message: string,
  senderName: string
): Promise<any> => {
  console.log('saveTargetMessage数据：',senderId,receiverId,timestamp,message,senderName);
  // 查找set里有没有对应的好友的消息，有就覆盖缓存，没有就创建文件
  const messageFile = await createMessageFile(receiverId, senderId, senderName);
  console.log('好友消息：',messageFile);
  if (messageFile) {
    friendsMessageMap.set(senderId, messageFile);
    friendsMessageSet.add(senderId);
  }

  //把消息写入内存
  friendsMessageMap
    .get(senderId)!
    .hisMessage.push({ time: timestamp, message });
  //从内存写入文件
  fs.writeFileSync(
    path.resolve(`${receiverId}\\${senderId}.json`),
    JSON.stringify(friendsMessageMap.get(senderId), null, 2),
    'utf-8'
  );
};
